<template>
  <div class="panel-tab__content">
    <a-table :data-source="elementListenersList" size="small" bordered>
      <a-table-column title="序号" width="50px">
        <template #customRender="{ index }">
          {{ index + 1 }}
        </template>
      </a-table-column>
      <a-table-column title="事件类型" width="80px">
        <template #customRender="{ record }">
          {{ listenerEventTypeObject[record.event] }}
        </template>
      </a-table-column>
      <a-table-column title="事件id" data-index="id" width="80px" />
      <a-table-column title="监听器类型" width="80px">
        <template #customRender="{ record }">
          {{ listenerTypeObject[record.listenerType] }}
        </template>
      </a-table-column>
      <a-table-column title="操作" width="90px">
        <template #customRender="{ record, index }">
          <a-space>
            <a @click="openListenerForm(record, index)">编辑</a>
            <a-divider type="vertical" />
            <a class="text-red" @click="removeListener(record, index)">移除</a>
          </a-space>
        </template>
      </a-table-column>
    </a-table>

    <div class="element-drawer__button">
      <a-button size="small" type="primary" @click="openListenerForm(null)">
        <template #icon><plus-outlined /></template>
        添加监听器
      </a-button>
    </div>

    <!-- 监听器 编辑/创建 部分 -->
    <a-drawer v-model:open="listenerFormModelVisible" title="任务监听器" :width="width" :destroy-on-close="true">
      <a-form ref="listenerFormRef" :model="listenerForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" size="small">
        <a-form-item label="事件类型" name="event" :rules="[{ required: true, message: '请选择事件类型' }]">
          <a-select v-model:value="listenerForm.event">
            <a-select-option v-for="(value, key) in listenerEventTypeObject" :key="key" :value="key">
              {{ value }}
            </a-select-option>
          </a-select>
        </a-form-item>

        <a-form-item label="监听器ID" name="id" :rules="[{ required: true, message: '请输入监听器ID' }]">
          <a-input v-model:value="listenerForm.id" allow-clear />
        </a-form-item>

        <a-form-item label="监听器类型" name="listenerType" :rules="[{ required: true, message: '请选择监听器类型' }]">
          <a-select v-model:value="listenerForm.listenerType">
            <a-select-option v-for="(value, key) in listenerTypeObject" :key="key" :value="key">
              {{ value }}
            </a-select-option>
          </a-select>
        </a-form-item>

        <a-form-item
          v-if="listenerForm.listenerType === 'classListener'"
          label="Java类"
          name="class"
          :rules="[{ required: true, message: '请输入Java类' }]"
        >
          <a-input v-model:value="listenerForm.class" allow-clear />
        </a-form-item>

        <a-form-item
          v-if="listenerForm.listenerType === 'expressionListener'"
          label="表达式"
          name="expression"
          :rules="[{ required: true, message: '请输入表达式' }]"
        >
          <a-input v-model:value="listenerForm.expression" allow-clear />
        </a-form-item>

        <a-form-item
          v-if="listenerForm.listenerType === 'delegateExpressionListener'"
          label="代理表达式"
          name="delegateExpression"
          :rules="[{ required: true, message: '请输入代理表达式' }]"
        >
          <a-input v-model:value="listenerForm.delegateExpression" allow-clear />
        </a-form-item>

        <template v-if="listenerForm.listenerType === 'scriptListener'">
          <a-form-item label="脚本格式" name="scriptFormat" :rules="[{ required: true, message: '请填写脚本格式' }]">
            <a-input v-model:value="listenerForm.scriptFormat" allow-clear />
          </a-form-item>

          <a-form-item label="脚本类型" name="scriptType" :rules="[{ required: true, message: '请选择脚本类型' }]">
            <a-select v-model:value="listenerForm.scriptType">
              <a-select-option value="inlineScript">内联脚本</a-select-option>
              <a-select-option value="externalScript">外部脚本</a-select-option>
            </a-select>
          </a-form-item>

          <a-form-item
            v-if="listenerForm.scriptType === 'inlineScript'"
            label="脚本内容"
            name="value"
            :rules="[{ required: true, message: '请填写脚本内容' }]"
          >
            <a-input v-model:value="listenerForm.value" allow-clear />
          </a-form-item>

          <a-form-item
            v-if="listenerForm.scriptType === 'externalScript'"
            label="资源地址"
            name="resource"
            :rules="[{ required: true, message: '请填写资源地址' }]"
          >
            <a-input v-model:value="listenerForm.resource" allow-clear />
          </a-form-item>
        </template>

        <template v-if="listenerForm.event === 'timeout'">
          <a-form-item label="定时器类型" name="eventDefinitionType">
            <a-select v-model:value="listenerForm.eventDefinitionType">
              <a-select-option value="date">日期</a-select-option>
              <a-select-option value="duration">持续时长</a-select-option>
              <a-select-option value="cycle">循环</a-select-option>
              <a-select-option value="null">无</a-select-option>
            </a-select>
          </a-form-item>

          <a-form-item
            v-if="!!listenerForm.eventDefinitionType && listenerForm.eventDefinitionType !== 'null'"
            label="定时器"
            name="eventTimeDefinitions"
            :rules="[{ required: true, message: '请填写定时器配置' }]"
          >
            <a-input v-model:value="listenerForm.eventTimeDefinitions" allow-clear />
          </a-form-item>
        </template>
      </a-form>

      <a-divider />
      <div class="list-header">
        <span><menu-outlined /> 注入字段：</span>
        <a-button size="small" type="primary" @click="openListenerFieldForm(null)">添加字段</a-button>
      </div>

      <a-table :data-source="fieldsListOfListener" size="small" :scroll="{ y: 240 }" bordered>
        <a-table-column title="序号" width="50px">
          <template #customRender="{ index }">
            {{ index + 1 }}
          </template>
        </a-table-column>
        <a-table-column title="字段名称" data-index="name" width="100px" />
        <a-table-column title="字段类型" width="80px">
          <template #customRender="{ record }">
            {{ fieldTypeObject[record.fieldType] }}
          </template>
        </a-table-column>
        <a-table-column title="字段值/表达式">
          <template #customRender="{ record }">
            {{ record.string || record.expression }}
          </template>
        </a-table-column>
        <a-table-column title="操作" width="100px">
          <template #customRender="{ record, index }">
            <a-space>
              <a @click="openListenerFieldForm(record, index)">编辑</a>
              <a-divider type="vertical" />
              <a class="text-red" @click="removeListenerField(record, index)">移除</a>
            </a-space>
          </template>
        </a-table-column>
      </a-table>

      <template #footer>
        <a-space>
          <a-button size="small" @click="listenerFormModelVisible = false">取 消</a-button>
          <a-button size="small" type="primary" @click="saveListenerConfig">保 存</a-button>
        </a-space>
      </template>
    </a-drawer>

    <!-- 注入字段 编辑/创建 部分 -->
    <a-modal v-model:open="listenerFieldFormModelVisible" title="字段配置" width="600px" :destroy-on-close="true" @ok="saveListenerFiled">
      <a-form ref="listenerFieldFormRef" :model="listenerFieldForm" :label-col="{ span: 6 }" :wrapper-col="{ span: 18 }" size="small">
        <a-form-item label="字段名称" name="name" :rules="[{ required: true, message: '请输入字段名称' }]">
          <a-input v-model:value="listenerFieldForm.name" allow-clear />
        </a-form-item>

        <a-form-item label="字段类型" name="fieldType" :rules="[{ required: true, message: '请选择字段类型' }]">
          <a-select v-model:value="listenerFieldForm.fieldType">
            <a-select-option v-for="(value, key) in fieldTypeObject" :key="key" :value="key">
              {{ value }}
            </a-select-option>
          </a-select>
        </a-form-item>

        <a-form-item
          v-if="listenerFieldForm.fieldType === 'string'"
          label="字段值"
          name="string"
          :rules="[{ required: true, message: '请输入字段值' }]"
        >
          <a-input v-model:value="listenerFieldForm.string" allow-clear />
        </a-form-item>

        <a-form-item
          v-if="listenerFieldForm.fieldType === 'expression'"
          label="表达式"
          name="expression"
          :rules="[{ required: true, message: '请输入表达式' }]"
        >
          <a-input v-model:value="listenerFieldForm.expression" allow-clear />
        </a-form-item>
      </a-form>
    </a-modal>
  </div>
</template>

<script>
  import { PlusOutlined, MenuOutlined } from '@ant-design/icons-vue';
  import { createListenerObject, updateElementExtensions } from '../../utils';
  import { initListenerForm, initListenerType, eventType, listenerType, fieldType } from './utilSelf';

  export default {
    name: 'UserTaskListeners',
    components: {
      PlusOutlined,
      MenuOutlined,
    },
    props: {
      id: String,
      type: String,
    },
    inject: {
      prefix: 'prefix',
      width: 'width',
    },
    data() {
      return {
        elementListenersList: [],
        listenerEventTypeObject: eventType,
        listenerTypeObject: listenerType,
        listenerFormModelVisible: false,
        listenerForm: {},
        fieldTypeObject: fieldType,
        fieldsListOfListener: [],
        listenerFieldFormModelVisible: false,
        editingListenerIndex: -1,
        editingListenerFieldIndex: -1,
        listenerFieldForm: {},
      };
    },
    watch: {
      id: {
        immediate: true,
        handler(val) {
          val && val.length && this.$nextTick(() => this.resetListenersList());
        },
      },
    },
    methods: {
      resetListenersList() {
        this.bpmnElement = window.bpmnInstances.bpmnElement;
        this.otherExtensionList = [];
        this.bpmnElementListeners =
          this.bpmnElement.businessObject?.extensionElements?.values?.filter((ex) => ex.$type === `${this.prefix}:TaskListener`) ?? [];
        this.elementListenersList = this.bpmnElementListeners.map((listener) => initListenerType(listener));
      },
      openListenerForm(listener, index) {
        if (listener) {
          this.listenerForm = initListenerForm(listener);
          this.editingListenerIndex = index;
        } else {
          this.listenerForm = {};
          this.editingListenerIndex = -1; // 标记为新增
        }
        if (listener && listener.fields) {
          this.fieldsListOfListener = listener.fields.map((field) => ({
            ...field,
            fieldType: field.string ? 'string' : 'expression',
          }));
        } else {
          this.fieldsListOfListener = [];
          this.listenerForm['fields'] = [];
        }
        // 打开侧边栏并清楚验证状态
        this.listenerFormModelVisible = true;
        this.$nextTick(() => {
          if (this.$refs['listenerFormRef']) this.$refs['listenerFormRef'].clearValidate();
        });
      },
      // 移除监听器
      removeListener(listener, index) {
        this.$confirm('确认移除该监听器吗？', '提示', {
          confirmButtonText: '确 认',
          cancelButtonText: '取 消',
        })
          .then(() => {
            this.bpmnElementListeners.splice(index, 1);
            this.elementListenersList.splice(index, 1);
            updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners));
          })
          .catch(() => console.info('操作取消'));
      },
      // 保存监听器
      async saveListenerConfig() {
        let validateStatus = await this.$refs['listenerFormRef'].validate();
        if (!validateStatus) return; // 验证不通过直接返回
        const listenerObject = createListenerObject(this.listenerForm, true, this.prefix);
        if (this.editingListenerIndex === -1) {
          this.bpmnElementListeners.push(listenerObject);
          this.elementListenersList.push(this.listenerForm);
        } else {
          this.bpmnElementListeners.splice(this.editingListenerIndex, 1, listenerObject);
          this.elementListenersList.splice(this.editingListenerIndex, 1, this.listenerForm);
        }
        // 保存其他配置
        this.otherExtensionList =
          this.bpmnElement.businessObject?.extensionElements?.values?.filter((ex) => ex.$type !== `${this.prefix}:TaskListener`) ?? [];
        updateElementExtensions(this.bpmnElement, this.otherExtensionList.concat(this.bpmnElementListeners));
        // 4. 隐藏侧边栏
        this.listenerFormModelVisible = false;
        this.listenerForm = {};
      },
      // 打开监听器字段编辑弹窗
      openListenerFieldForm(field, index) {
        this.listenerFieldForm = field ? JSON.parse(JSON.stringify(field)) : {};
        this.editingListenerFieldIndex = field ? index : -1;
        this.listenerFieldFormModelVisible = true;
        this.$nextTick(() => {
          if (this.$refs['listenerFieldFormRef']) this.$refs['listenerFieldFormRef'].clearValidate();
        });
      },
      // 保存监听器注入字段
      async saveListenerFiled() {
        let validateStatus = await this.$refs['listenerFieldFormRef'].validate();
        if (!validateStatus) return; // 验证不通过直接返回
        if (this.editingListenerFieldIndex === -1) {
          this.fieldsListOfListener.push(this.listenerFieldForm);
          this.listenerForm.fields.push(this.listenerFieldForm);
        } else {
          this.fieldsListOfListener.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm);
          this.listenerForm.fields.splice(this.editingListenerFieldIndex, 1, this.listenerFieldForm);
        }
        this.listenerFieldFormModelVisible = false;
        this.$nextTick(() => (this.listenerFieldForm = {}));
      },
      // 移除监听器字段
      removeListenerField(field, index) {
        this.$confirm('确认移除该字段吗？', '提示', {
          confirmButtonText: '确 认',
          cancelButtonText: '取 消',
        })
          .then(() => {
            this.fieldsListOfListener.splice(index, 1);
            this.listenerForm.fields.splice(index, 1);
          })
          .catch(() => console.info('操作取消'));
      },
    },
  };
</script>

<style>
  .panel-tab__content {
    padding: 8px;
  }

  .list-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 8px;
  }

  .list-header span {
    display: flex;
    align-items: center;
    gap: 8px;
  }

  .text-red {
    color: #ff4d4f;
  }

  .element-drawer__button {
    margin-top: 8px;
    text-align: right;
  }
</style>
